﻿/*
 * Credits to cablehead @ http://social.msdn.microsoft.com/en-US/profile/?user=cablehead&referrer=http%3A//social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/03a8c835-e9e4-405b-8345-6c3d36bc8941/#sort=recent&page=0&filter=allcontent
 * for this class that I modified slightly to suit my needs
 * 
 * Qiong Wu
 * 24th March 2009
 *  
 * */

using System;
using System.Collections.Generic;
using Accessibility;
using System.Runtime.InteropServices;
using System.Diagnostics;
using SHDocVw;

namespace IEAccessibleTabs
{
    public class IEAccessible
    {
        private enum OBJID : uint
        {
            OBJID_WINDOW = 0x00000000,
        }

        private const int IE_ACTIVE_TAB = 2097154;
        private const int CHILDID_SELF = 0;

        private IAccessible accessible;

        private IEAccessible[] Children
        {
            get
            {
                int num = 0;
                object[] res = GetAccessibleChildren(accessible, out num);

                if (res == null)
                    return new IEAccessible[0];

                List<IEAccessible> list = new List<IEAccessible>(res.Length);

                foreach (object obj in res)
                {
                    IAccessible acc = obj as IAccessible;
                    if (acc != null)
                        list.Add(new IEAccessible(acc));
                }

                return list.ToArray();
            }

        }

        private string Name
        {

            get
            {

                string ret = accessible.get_accName(CHILDID_SELF);

                return ret;

            }

        }

        private string URL
        {

            get
            {
                string ret;
                try
                {
                    ret = accessible.get_accDescription(CHILDID_SELF).Split(new string[1] { "\r\n" }, StringSplitOptions.None)[1];
                }
                catch
                {
                    ret = "";
                }
                return ret;

            }

        }

        private int ChildCount
        {

            get
            {

                int ret = accessible.accChildCount;

                return ret;

            }

        }



        public IEAccessible()
        {



        }

        public IEAccessible(IntPtr ieHandle, string tabCaptionToActivate)
        {

            AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref accessible);

            if (accessible == null)

                throw new Exception();



            var ieDirectUIHWND = new IEAccessible(ieHandle);



            foreach (IEAccessible accessor in ieDirectUIHWND.Children)
            {

                foreach (var child in accessor.Children)
                {

                    foreach (var tab in child.Children)
                    {

                        if (tab.Name == tabCaptionToActivate)
                        {
                            tab.Activate();

                            return;

                        }

                    }

                }

            }

        }

        public IEAccessible(IntPtr ieHandle, int tabIndexToActivate)
        {

            AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref accessible);

            if (accessible == null)

                throw new Exception();



            var index = 0;

            var ieDirectUIHWND = new IEAccessible(ieHandle);



            foreach (IEAccessible accessor in ieDirectUIHWND.Children)
            {

                foreach (var child in accessor.Children)
                {

                    foreach (var tab in child.Children)
                    {

                        if (tabIndexToActivate >= child.ChildCount - 1) return;

                        if (index == tabIndexToActivate)
                        {

                            tab.Activate();

                            return;

                        }

                        index++;

                    }

                }

            }

        }

        private IEAccessible(IntPtr ieHandle)
        {

            AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref accessible);

            if (accessible == null)

                throw new Exception();

        }

        public string GetActiveTabUrl(IntPtr ieHandle)
        {

            AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref accessible);

            if (accessible == null)

                throw new Exception();



            var ieDirectUIHWND = new IEAccessible(ieHandle);



            foreach (IEAccessible accessor in ieDirectUIHWND.Children)
            {

                foreach (var child in accessor.Children)
                {

                    foreach (var tab in child.Children)
                    {

                        object tabIndex = tab.accessible.get_accState(CHILDID_SELF);



                        if ((int)tabIndex == IE_ACTIVE_TAB)
                        {

                            var description = tab.accessible.get_accDescription(CHILDID_SELF);



                            if (!string.IsNullOrEmpty(description))
                            {

                                if (description.Contains(Environment.NewLine))
                                {

                                    var url = description.Substring(description.IndexOf(Environment.NewLine)).Trim();

                                    return url;

                                }

                            }

                        }

                    }

                }

            }



            return String.Empty;

        }

        public int GetActiveTabIndex(IntPtr ieHandle)
        {

            AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref accessible);

            if (accessible == null)

                throw new Exception();



            var index = 0;

            var ieDirectUIHWND = new IEAccessible(ieHandle);



            foreach (IEAccessible accessor in ieDirectUIHWND.Children)
            {

                foreach (var child in accessor.Children)
                {
                    foreach (var tab in child.Children)
                    {
                        object tabIndex = tab.accessible.get_accState(0);
                        if ((int)tabIndex == IE_ACTIVE_TAB)
                            return index;
                        index++;
                    }
                }
            }

            return -1;
        }

        public string GetActiveTabCaption(IntPtr ieHandle)
        {

            AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref accessible);

            if (accessible == null)

                throw new Exception();



            var ieDirectUIHWND = new IEAccessible(ieHandle);



            foreach (IEAccessible accessor in ieDirectUIHWND.Children)
            {

                foreach (var child in accessor.Children)
                {

                    foreach (var tab in child.Children)
                    {

                        object tabIndex = tab.accessible.get_accState(0);



                        if ((int)tabIndex == IE_ACTIVE_TAB)

                            return tab.Name;

                    }

                }

            }

            return String.Empty;

        }

        public List<string> GetTabCaptions(IntPtr ieHandle)
        {
            AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref accessible);
            if (accessible == null)
                throw new Exception();
            var ieDirectUIHWND = new IEAccessible(ieHandle);
            var captionList = new List<string>();

            foreach (IEAccessible accessor in ieDirectUIHWND.Children)
            {
                foreach (var child in accessor.Children)
                    foreach (var tab in child.Children)
                        captionList.Add(tab.Name);
            }

            if (captionList.Count > 0)

                captionList.RemoveAt(captionList.Count - 1);



            return captionList;



        }

        public List<string> GetTabURLs(IntPtr ieHandle)
        {
            AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref accessible);
            if (accessible == null)
                throw new Exception();
            var ieDirectUIHWND = new IEAccessible(ieHandle);
            var captionList = new List<string>();

            foreach (IEAccessible accessor in ieDirectUIHWND.Children)
            {
                foreach (var child in accessor.Children)
                    foreach (var tab in child.Children)
                        captionList.Add(tab.URL);
            }

            if (captionList.Count > 0)

                captionList.RemoveAt(captionList.Count - 1);



            return captionList;



        }

        public int GetTabCount(IntPtr ieHandle)
        {

            AccessibleObjectFromWindow(GetDirectUIHWND(ieHandle), OBJID.OBJID_WINDOW, ref accessible);

            if (accessible == null)

                throw new Exception();



            var ieDirectUIHWND = new IEAccessible(ieHandle);



            foreach (IEAccessible accessor in ieDirectUIHWND.Children)
            {

                foreach (var child in accessor.Children)
                {

                    foreach (var tab in child.Children)

                        return child.ChildCount - 1;

                }

            }

            return 0;



        }



        private IntPtr GetDirectUIHWND(IntPtr ieFrame)
        {

            var directUI = FindWindowEx(ieFrame, IntPtr.Zero, "CommandBarClass", null);
            directUI = FindWindowEx(directUI, IntPtr.Zero, "ReBarWindow32", null);
            directUI = FindWindowEx(directUI, IntPtr.Zero, "TabBandClass", null);
            directUI = FindWindowEx(directUI, IntPtr.Zero, "DirectUIHWND", null);

            return directUI;
        }

        private IEAccessible(IAccessible acc)
        {

            if (acc == null)

                throw new Exception();

            accessible = acc;

        }

        private void Activate()
        {
            accessible.accDoDefaultAction(CHILDID_SELF);
        }

        private static object[] GetAccessibleChildren(IAccessible ao, out int childs)
        {

            childs = 0;

            object[] ret = null;

            int count = ao.accChildCount;

            if (count > 0)
            {

                ret = new object[count];

                AccessibleChildren(ao, 0, count, ret, out childs);

            }

            return ret;

        }

        public static List<InternetExplorer> GetBrowserObjectsFromHandle(IntPtr Handle)
        {
            List<InternetExplorer> ReturnList = new List<InternetExplorer>();
            SHDocVw.ShellWindowsClass shellWindows = new SHDocVw.ShellWindowsClass();
            
            foreach (SHDocVw.InternetExplorer ie in shellWindows)
            {
                try
                {

                    if (ie.HWND == Handle.ToInt32())
                    {
                        ReturnList.Add(ie);
                    }
                }
                catch
                {

                }
            }

            return ReturnList;
        }

        public static InternetExplorer GetTabBrowserObjectFromHandle(int Handle1,IntPtr Handle)
        {
            SHDocVw.ShellWindowsClass shellWindows = new SHDocVw.ShellWindowsClass();
            Guid IIDWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
            Guid IIDWebBrowser2 = new Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E");
            Guid iid = new Guid("00000000-0000-0000-C000-000000000046"); // IID_IUnknown
            Guid SID_SShellBrowser = new Guid("000214E2-0000-0000-C000-000000000046");
            Guid BrowserGUID = new Guid("00000114-0000-0000-C000-000000000046");


            foreach (InternetExplorer ie in shellWindows)
            {
                try
                {
                    if (ie.HWND == Handle1)
                    {
                        TabSaver.IServiceProvider BrowserServiceProvider = ie as TabSaver.IServiceProvider;
                        
                        IntPtr newBrowser;
                        BrowserServiceProvider.QueryService(ref SID_SShellBrowser, ref BrowserGUID, out newBrowser);

                        SpicIE.Common.IOleWindow Bowser = Marshal.GetObjectForIUnknown(newBrowser) as SpicIE.Common.IOleWindow;
                        IntPtr Hwnd;
                        Bowser.GetWindow(out Hwnd);

                        if (Hwnd == Handle)
                        {
                            return ie;
                        }
                    }
                }
                catch (Exception e)
                {

                }
            }

            return null;
        }

        #region Interop
        [DllImport("user32.dll", SetLastError = true)]

        private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass,

        string lpszWindow);

        private static int AccessibleObjectFromWindow(IntPtr hwnd, OBJID idObject, ref IAccessible acc)
        {
            Guid guid = new Guid("{618736e0-3c3d-11cf-810c-00aa00389b71}"); // IAccessible
            //Guid guid = new Guid("{D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}"); //IWebBrowser2

            object obj = null;
            int num = AccessibleObjectFromWindow(hwnd, (uint)idObject, ref guid, ref obj);

            acc = (IAccessible)obj;

            return num;

        }

        [DllImport("ole32.Dll")]
        static public extern uint CoCreateInstance(ref Guid clsid, [MarshalAs(UnmanagedType.IUnknown)] object inner, uint context, ref Guid uuid, [MarshalAs(UnmanagedType.IUnknown)] out object rReturnedComObject);


        [DllImport("oleacc.dll")]

        private static extern int AccessibleObjectFromWindow(IntPtr hwnd, uint id, ref Guid iid, [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject);

        [DllImport("oleacc.dll")]

        private static extern int AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] object[] rgvarChildren, out int pcObtained);

        #endregion

    }





}
